package com.gwtintegration.smartrf.builder;

import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.gwtintegration.smartrf.client.Attribute;

public class JMethodUtils {

	private JMethodUtils() {}

	public static boolean isGetter(JMethod method) {
		return method.getName().startsWith("get") || method.getName().startsWith("is");
	}

	public static boolean isSetter(JMethod method) {
		return method.getName().startsWith("set");
	}

	public static boolean isPrimaryKey(JMethod method) {
		Attribute attribute = getAttribute(method);
		return attribute != null && attribute.primaryKey();
	}

	public static Attribute getAttribute(JMethod method) {
		Attribute attribute = method.getAnnotation(Attribute.class);

		if (attribute == null && isSetter(method)) {
			JMethod getterMethod = getGetter(method);
			attribute = getterMethod != null ? getterMethod.getAnnotation(Attribute.class) : null;
		}

		return attribute;
	}

	public static JMethod getGetter(JMethod method) {
		String varName = getVariableName(method);
		String getterName = "get" + Character.toUpperCase(varName.charAt(0)) + varName.substring(1);
		return method.getEnclosingType().findMethod(getterName, new JType[] {});
	}

	public static JMethod getSetter(JMethod method) {
		String varName = getVariableName(method);
		String setterName = "set" + Character.toUpperCase(varName.charAt(0)) + varName.substring(1);
		return method.getEnclosingType().findMethod(setterName, new JType[] { method.getReturnType() });
	}

	public static String getAttributeName(JMethod method) {
		Attribute attribute = getAttribute(method);
		if (attribute != null && !attribute.name().isEmpty()) {
			return method.getAnnotation(Attribute.class).name();
		}

		return getVariableName(method);
	}

	public static String getVariableName(JMethod method) {
		if (method == null) {
			throw new IllegalArgumentException("method can't be null.");
		}

		String name = method.getName();
		if (name.startsWith("is")) {
			return Character.toLowerCase(name.charAt(2)) + name.substring(3);
		} else if (name.startsWith("get") || name.startsWith("set")) {
			return Character.toLowerCase(name.charAt(3)) + name.substring(4);
		}

		throw new IllegalArgumentException(name + " is not a valid name for a proxy method.");
	}

	public static JClassType getSingleParameterType(JMethod method) {
		JType[] parameterTypes = method.getParameterTypes();

		if (parameterTypes != null && parameterTypes.length > 0) {
			return parameterTypes[0].isClassOrInterface();
		}

		return null;
	}
}
